package com.platform.qujia.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.platform.qujia.dao.AppUserInfoMapper;
import com.platform.qujia.dao.IntegralDeductionActivityMapper;
import com.platform.qujia.dao.IntegralDeductionRuleMapper;
import com.platform.qujia.enums.ActionTypeEnum;
import com.platform.qujia.enums.DeductionRuleType;
import com.platform.qujia.pojo.*;
import com.platform.qujia.pojo.dto.IntegralDeductionActivityDto;
import com.platform.qujia.service.CustomerPointsRecordService;
import com.platform.qujia.service.IntegralDeductionActivityService;
import com.platform.qujia.service.PayOrderService;
import com.platform.qujia.utils.DateUtils;
import com.platform.qujia.utils.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;


@Service("integralDeductionActivityService")
@Slf4j
public class IntegralDeductionActivityServiceImpl implements IntegralDeductionActivityService {

    @Autowired
    private IntegralDeductionActivityMapper integralDeductionActivityMapper;

    @Autowired
    private AppUserInfoMapper appUserInfoMapper;

    @Autowired
    private IntegralDeductionRuleMapper integralDeductionRuleMapper;

    @Autowired
    private PayOrderService payOrderService;

    @Autowired
    private CustomerPointsRecordService customerPointsRecordService;


    @Override
    public IntegralDeductionActivityDto selectIntegralDeductionActivity(IntegralDeductionActivityDto integralDeductionActivityDto) {
        if(StringUtils.isEmpty(integralDeductionActivityDto.getOrderNo())){
            throw new CustomException("订单不存在");
        }
        log.info("积分抵扣现金selectIntegralDeductionActivity 请求参数:[{}]",JSONObject.toJSONString(integralDeductionActivityDto));
        AppUserInfo appUser = appUserInfoMapper.getAppUserById(integralDeductionActivityDto.getUserId());
        // 没积分
        if(Objects.isNull(appUser.getIntegral()) || appUser.getIntegral() <= 0){
            integralDeductionActivityDto.setIntegral(0);
            integralDeductionActivityDto.setIntegralDeductionNum(0L);
            integralDeductionActivityDto.setIntegralDeductionAmt(BigDecimal.ZERO);
            return integralDeductionActivityDto;
        }
        Integer integral = appUser.getIntegral();
        integralDeductionActivityDto.setIntegral(integral);

        // 积分查询积分活动
        IntegralDeductionActivity req = new IntegralDeductionActivity();
        req.setStationId(integralDeductionActivityDto.getStationId());
        String nowTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,new Date());
        req.setNowTime(nowTime);
        IntegralDeductionActivity integralDeductionActivity = integralDeductionActivityMapper.selectIntegralDeductionActivityLast(req);
        // 没活动
        if(Objects.isNull(integralDeductionActivity) || Objects.isNull(integralDeductionActivity.getActivityId())){
            integralDeductionActivityDto.setIntegral(integral);
            integralDeductionActivityDto.setIntegralDeductionNum(0L);
            integralDeductionActivityDto.setIntegralDeductionAmt(BigDecimal.ZERO);
            return integralDeductionActivityDto;
        }

        IntegralDeductionRule integralDeductionRule = integralDeductionRuleMapper.selectByActivityId(integralDeductionActivity.getActivityId());
        // 活动没有规则
        if(Objects.isNull(integralDeductionRule)){
            integralDeductionActivityDto.setIntegral(integral);
            integralDeductionActivityDto.setIntegralDeductionNum(0L);
            integralDeductionActivityDto.setIntegralDeductionAmt(BigDecimal.ZERO);
            return integralDeductionActivityDto;
        }

        if(DeductionRuleType.NO_LIMIT.getValue().equals(integralDeductionRule.getRuleType())){
            noLimit(integral,integralDeductionActivityDto,integralDeductionRule);
        } else if(DeductionRuleType.FIXED_LIMIT.getValue().equals(integralDeductionRule.getRuleType())){
            fixedLimit(integral,integralDeductionActivityDto,integralDeductionRule);
        }else if(DeductionRuleType.GRADIENT_LIMIT.getValue().equals(integralDeductionRule.getRuleType())){
            gradientLimit(integral,integralDeductionActivityDto,integralDeductionRule);
        }
        log.info("积分抵扣现金selectIntegralDeductionActivity 返回结果:[{}]",JSONObject.toJSONString(integralDeductionActivityDto));
        return integralDeductionActivityDto;
    }

    // 不限制积分规则计算积分
    private void noLimit(Integer integral, IntegralDeductionActivityDto integralDeductionActivityDto, IntegralDeductionRule integralDeductionRule){
        // 总积分
        integralDeductionActivityDto.setIntegral(integral);
        integralDeductionActivityDto.setIntegralDeductionNum(0L); // 使用的积分
        integralDeductionActivityDto.setIntegralDeductionAmt(BigDecimal.ZERO); // 积分抵扣金额

        if(Objects.isNull(integralDeductionRule.getIntegralNum()) || Objects.isNull(integralDeductionRule.getAmt())){
            return;
        }

        BigDecimal orderAmt = integralDeductionActivityDto.getAmt();

        // 剩余积分
        integral = useIntegral(integral, integralDeductionActivityDto, integralDeductionRule, orderAmt);

    }

    // 固定限制积分计算
    private void fixedLimit(Integer integral, IntegralDeductionActivityDto integralDeductionActivityDto, IntegralDeductionRule integralDeductionRule){
        // 总积分
        integralDeductionActivityDto.setIntegral(integral);
        integralDeductionActivityDto.setIntegralDeductionNum(0L);
        integralDeductionActivityDto.setIntegralDeductionAmt(BigDecimal.ZERO);

        if(Objects.isNull(integralDeductionRule.getIntegralNum()) || Objects.isNull(integralDeductionRule.getAmt())
                || CollectionUtils.isEmpty(integralDeductionRule.getGradientRuleList())){
            return;
        }

        // 目前固定限制积分只有一条数据，只有一个最大允许抵扣金额
        BigDecimal maxDeductionAmt = integralDeductionRule.getGradientRuleList().get(0).getMaxAmt();

        BigDecimal orderAmt = integralDeductionActivityDto.getAmt();

        // 先判断是否超出最大允许额度 超出最大允许抵扣额度
        if(orderAmt.compareTo(maxDeductionAmt) >= 0){
            // 剩余积分
            integral = useIntegral(integral, integralDeductionActivityDto, integralDeductionRule, maxDeductionAmt);

        }else {
            // 根据订单实付金额 扣减积分
            integral = useIntegral(integral, integralDeductionActivityDto, integralDeductionRule, orderAmt);
        }

    }

    // 根据梯度计算积分
    private void gradientLimit(Integer integral, IntegralDeductionActivityDto integralDeductionActivityDto, IntegralDeductionRule integralDeductionRule){
        // 总积分
        integralDeductionActivityDto.setIntegral(integral);
        integralDeductionActivityDto.setIntegralDeductionNum(0L);
        integralDeductionActivityDto.setIntegralDeductionAmt(BigDecimal.ZERO);

        if(Objects.isNull(integralDeductionRule.getIntegralNum()) || Objects.isNull(integralDeductionRule.getAmt())
                || CollectionUtils.isEmpty(integralDeductionRule.getGradientRuleList())){
            return;
        }

        // 满足梯度抵扣实付金额的最大
        BigDecimal maxDeductionAmt = BigDecimal.ZERO;

        BigDecimal orderAmt = integralDeductionActivityDto.getAmt();

        // 梯度限制规则
        for (GradientRule gradientRule : integralDeductionRule.getGradientRuleList()) {
            if(gradientRule.getAmt().compareTo(orderAmt) >= 0){
                maxDeductionAmt = gradientRule.getMaxAmt();
                break;
            }
        }

        // 先判断是否超出最大允许额度 超出最大允许抵扣额度
        if(orderAmt.compareTo(maxDeductionAmt) >= 0){
            // 剩余积分
            integral = useIntegral(integral, integralDeductionActivityDto, integralDeductionRule, maxDeductionAmt);

        }else {
            // 根据订单实付金额 扣减积分
            integral = useIntegral(integral, integralDeductionActivityDto, integralDeductionRule, orderAmt);
        }

    }

    // 根据积分规则扣减积分
    private Integer useIntegral(Integer integral, IntegralDeductionActivityDto integralDeductionActivityDto, IntegralDeductionRule integralDeductionRule,
                                BigDecimal maxDeductionAmt){

        Long integralNum = integralDeductionRule.getIntegralNum(); // 积分
        BigDecimal amt = integralDeductionRule.getAmt(); // 抵扣金额

        // 抵扣次数
        double deductionNum = Math.floor(integral.doubleValue()/integralNum.doubleValue());
        // 不能抵扣
        if(deductionNum <= 0){
            return 0;
        }

        // 使用积分
        long allUsedIntegral;
        // 抵扣金额
        BigDecimal allDeductionAmt = BigDecimal.ZERO;

        // 积分 最大可抵扣金额
        BigDecimal maxAmt = amt.multiply(BigDecimal.valueOf(deductionNum));

        // 可以使用最大抵扣金额  积分全用完
        if(maxDeductionAmt.compareTo(maxAmt) >= 0){
            allUsedIntegral = (long) (deductionNum * integralNum);

            // 剩余积分
            integral = Math.toIntExact(integral - allUsedIntegral);
            allDeductionAmt = maxAmt;
        } else {
            // 可使用抵扣积分规则次数  使用部分积分  使用divideToIntegralValue进行除法运算并取整
            BigDecimal num = maxDeductionAmt.divideToIntegralValue(amt);
            allUsedIntegral = (num.longValue() * integralNum);
            allDeductionAmt = num.multiply(amt);

            // 剩余积分
            integral = Math.toIntExact(integral - allUsedIntegral);
        }

        integralDeductionActivityDto.setIntegralDeductionNum(allUsedIntegral);
        integralDeductionActivityDto.setIntegralDeductionAmt(allDeductionAmt);
        integralDeductionActivityDto.setIntegralActivityId(integralDeductionRule.getActivityId());
        // 剩余积分
        return integral;
    }

    @Override
    @Transactional
    public void updateIntegral(String orderNo) {
        PayOrder payOrder = payOrderService.selectOrderInfoByOrdNo(orderNo);
        if(Objects.isNull(payOrder) || Objects.isNull(payOrder.getConsumerId())){
            log.info("该订单不是会员订单:[{}]",orderNo);
            return ;
        }
        if(Objects.isNull(payOrder.getIntegralDeductionNum()) || payOrder.getIntegralDeductionNum() <= 0){
            return;
        }
        log.info("updateIntegral 积分抵扣现金扣减积分：[{}]", JSONObject.toJSONString(payOrder));
        // 修改积分
        Integer userId = payOrder.getConsumerId();
        AppUserInfo appUser = appUserInfoMapper.getAppUserById(Long.valueOf(userId));
        appUser.setIntegral((int) (appUser.getIntegral() - payOrder.getIntegralDeductionNum()));
        appUserInfoMapper.updateAppUserInfoByUserId(appUser);

        // 新增积分明细
        CustomerPointsRecord customerPointsRecord = new CustomerPointsRecord();
        customerPointsRecord.setCustomerName(appUser.getBlogNickName());
        customerPointsRecord.setAction(ActionTypeEnum.DEDUCTION_ACTIVITY.getName());
        customerPointsRecord.setRecordType("-");
        customerPointsRecord.setIntegral(payOrder.getIntegralDeductionNum().intValue());
        customerPointsRecord.setCreateTime(new Date());
        customerPointsRecord.setStationId(payOrder.getStationId());
        customerPointsRecord.setStationName(payOrder.getStationName());
        customerPointsRecord.setOrderNo(payOrder.getOrderNo());
        customerPointsRecord.setMobilePhone(appUser.getMobilePhone());

        customerPointsRecordService.insertCustomerPointsRecordInfo(customerPointsRecord);

    }

}
